package io.nextop.cordova; import io.nextop.Id; import io.nextop.Message; import io.nextop.Route; import io.nextop.WireValue; import org.apache.cordova.CordovaPlugin; import org.apache.cordova.CordovaArgs; import org.apache.cordova.CallbackContext; import org.json.JSONArray; import org.json.JSONObject; import org.json.JSONException; import java.util.Map; import java.util.HashMap; import java.util.Queue; import java.util.LinkedList; import java.util.Iterator; import java.lang.Override; import rx.Observer; // FIXME set e X-Requested-With header to XMLHttpRequest // see http://stackoverflow.com/questions/15945118/detecting-ajax-requests-on-nodejs-with-express public class Nextop extends CordovaPlugin implements io.nextop.NextopContext { private io.nextop.Nextop nextop; /** JS id to Nextop Id forward-translation **/ Map<Integer, Id> idTranslationMap = new HashMap<Integer, Id>(32); public Nextop() { } @Override public io.nextop.Nextop getNextop() { return nextop; } @Override protected void pluginInitialize() { String accessKey = preferences.getString("NextopAccessKey", null); // TODO String[] grantKeys = new String[0]; nextop = io.nextop.Nextop.create(cordova.getActivity(), accessKey, grantKeys).start(); } @Override public void onDestroy() { nextop = nextop.stop(); } @Override public boolean execute(String action, CordovaArgs args, final CallbackContext callbackContext) throws JSONException { // id is always [0] then action-specific args follow final int id = args.getInt(0); if ("send".equals(action)) { JSONObject requestArgs = args.getJSONObject(1); Message.Builder builder = Message.newBuilder() .setRoute(Route.valueOf(requestArgs.getString("method") + " " + requestArgs.getString("url"))); // headers String mimeType = requestArgs.optString("mimeType"); if (null != mimeType) { builder.setHeader("Content-Type", mimeType); // can be overridden below } JSONObject requestHeaders = requestArgs.optJSONObject("requestHeaders"); if (null != requestHeaders) { for (Iterator itr = requestHeaders.keys(); itr.hasNext(); ) { String key = (String) itr.next(); String value = requestHeaders.getString(key); builder.setHeader(key, value); } } Message message = builder.build(); // track it idTranslationMap.put(id, message.id); // send it nextop.send(message).subscribe(new Observer<Message>() { Queue<Message> chunks = new LinkedList<Message>(); @Override public void onNext(Message t) { chunks.add(t); } @Override public void onCompleted() { idTranslationMap.remove(id); // FIXME merge the chunks; currently only do one Message head = chunks.poll(); if (null != head) { try { JSONObject responseArgs = new JSONObject(); responseArgs.put("status", head.getCode()); responseArgs.put("statusText", head.getReason()); // headers JSONObject responseHeaders = new JSONObject(); for (Map.Entry<WireValue, WireValue> e : head.headers.entrySet()) { responseHeaders.put(e.getKey().toText(), e.getValue().toText()); } // FIXME copy response type correctly responseArgs.put("responseText", head.getContent().toText()); callbackContext.success(responseArgs); } catch (JSONException e) { // could not create json callbackContext.error(/* FIXME */ 0); } } else { callbackContext.error(/* FIXME */ 0); } } @Override public void onError(Throwable e) { idTranslationMap.remove(id); callbackContext.error(/* FIXME */ 0); } }); return true; } else if ("abort".equals(action)) { Id messageId = idTranslationMap.get(id); if (null != messageId) { nextop.cancelSend(messageId); } return true; } else { return false; } } }